package com.qiwenshare.stock.strategy;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qiwenshare.stock.api.IStockDayInfoService;
import com.qiwenshare.stock.api.IStockWeekInfoService;
import com.qiwenshare.stock.domain.StockDayInfo;
import com.qiwenshare.stock.domain.StockInfo;
import com.qiwenshare.stock.domain.StockWeekInfo;
import com.qiwenshare.stock.service.StockDayInfoService;
import com.qiwenshare.stock.service.StockService;
import com.qiwenshare.stock.service.StockWeekInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Calendar;
import java.util.List;

/**
 * @ClassName WeekBreakStrategy
 * @Description TODO
 * @Author peng.zhang
 * @Date 2023/6/13 17:08
 * @Version 1.0
 * 注意事项：
 * 1、选股必须先分析其平均线系统排列的情况，认清该股目前所处的形势。
 * 2、选股应选择均线系统呈多头排列的股票，这些股呈强势，获利的机会大。
 * 3、平均线反映的是大众平均持股成本，通过分析股价与均线位置之间的关系，可以估计目前市场上获利抛压及空头回补意愿的强弱。
 * 4、在趋势未改变之前不要抛出手中的股票。
 * 5、选股务必分析短期的乖离率，不宜介入乖离率太大的股票。
 * 6、短期均线急速上扬的股票必须注意。
 * 7、强势股也应具有强势均线系统，往往在回档至均线附近即获支持，这正是买入时机。
 **/
@Slf4j
@Component
public class WeekBreakStrategy {
    @Resource
    private StockService stockService;
    @Resource
    private IStockWeekInfoService stockWeekInfoService;
    @Resource
    private IStockDayInfoService stockDayInfoService;

    /**
     * 买入点
     *
     * @param stockNum
     * @param date
     * @return
     */
    public double buyPrice(String stockNum, String date) {
        /**
         * 1、选股：选10周均线趋势向上的个股。坚决回避10周均线趋势向下的个股;
         * 2、介入点：强势股5，10，20，30周线正排列向上并且周线排列开口不大时，股价回档5周均线附近;
         * 3、介入点2：10周均线趋势向上，股价回档十周均线附近。
         * 4、介入点3：横盘股，选择10，20，30周线粘合的个股。
         * 5、介入点4：10周均线趋势向上，如果股价跌破10周均线，可在20，30周均线之上考虑介入，但如果跌破30周均线，跑。
         * 6、跑——股价上涨后，从向上下跌破10周均线且10周均线有拐头向下的趋势，快跑。
         */
        try {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.le("date", date);
            queryWrapper.eq("stock_num", stockNum);
            queryWrapper.orderByDesc("date");
            queryWrapper.last(" limit 3");
            List<StockWeekInfo> threeList = stockWeekInfoService.list(queryWrapper);
            if (threeList == null || threeList.size() < 3) {
                return -1;
            }
            StockWeekInfo info1 = threeList.get(2);
            StockWeekInfo info2 = threeList.get(1);
            StockWeekInfo info3 = threeList.get(0);
            //10周线趋势向上
            if (info1.getMa10() < info2.getMa10() && info2.getMa10() < info3.getMa10()) {
                //强势股5，10，20，30周线正排列向上时并周线排列开口不大时;
                //正排列
//                if (info3.getMa5() < info3.getMa10() && info3.getMa10() < info3.getMa20() && info3.getMa20() < info3.getMa30()) {
                //向上
//                    if (info1.getMa5() < info2.getMa5() && info2.getMa5() < info3.getMa5()
//                            && info1.getMa10() < info2.getMa10() && info2.getMa10() < info3.getMa10()
//                            && info1.getMa20() < info2.getMa20() && info2.getMa20() < info3.getMa20()
//                            && info1.getMa30() < info2.getMa30() && info2.getMa30() < info3.getMa30()
//                    ) {
                //股价回档10周均线附近
//                    if (Math.abs(info3.getMa10() - info3.getClose()) / info3.getClose() < 0.01) {
//                        return info3.getClose();
//                    }
                //股价回档5周均线附近
                if (Math.abs(info3.getMa5() - info3.getClose()) / info3.getClose() < 0.01) {
                    return info3.getClose();
                }
            }
//                }
//            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 卖点
     *
     * @param stockNum
     * @param date
     * @return
     */
    public static double sellPrice(String stockNum, String date) {
        //股价上涨后，从上向下跌破10周均线且10周均线有拐头向下的趋势，快跑
        try {
        } catch (Exception e) {
        }
        return -1;
    }

    public void backTest(String start, String end) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.parseDate(start));
        calendar.add(Calendar.DAY_OF_YEAR, 7);
        String nextWeekDay = DateUtil.format(calendar.getTime(), "YYYY-MM-dd");
        List<StockInfo> list = stockService.list();
        int successCount = 0;
        int failCount = 0;
        for (StockInfo s : list) {
            double buyPrice = buyPrice(s.getStockNum(), start);
            if (buyPrice > 0) {
                QueryWrapper queryWrapper = new QueryWrapper();
                queryWrapper.le("date", nextWeekDay);
                queryWrapper.eq("stock_num", s.getStockNum());
                queryWrapper.orderByDesc("date");
                queryWrapper.last(" limit 1");
                StockDayInfo currentInfo = stockDayInfoService.getOne(queryWrapper);
                log.info("stockNum:{},stockName:{},buy price:{},current price:{},ratio:{}",
                        currentInfo.getStockNum(),
                        currentInfo.getStockName(),
                        buyPrice,
                        currentInfo.getClose(),
                        (currentInfo.getClose() - buyPrice) / buyPrice * 100
                );
                if (buyPrice < currentInfo.getClose()) {
                    successCount++;
                } else {
                    failCount++;
                }
            }
        }
        log.info("success count:{},fail count:{}", successCount, failCount);
    }
}
